import os
import zipfile
import toml
import json
import urllib.request
import urllib.error
import requests
from .mod_classifier import ModClassifier

class ServerCreator:
    def __init__(self):
        self.classifier = ModClassifier()
        # 添加镜像源配置
        self.mirror_sources = "https://bmclapi2.bangbang93.com/maven"
        
    def get_mod_dependencies(self, mod_file_path):
        """
        获取mod的前置依赖（通过读取mods.toml或fabric.mod.json文件）
        返回: dependencies列表
        """
        dependencies = []
        
        try:
            # 尝试从jar文件中读取mods.toml或fabric.mod.json文件
            with zipfile.ZipFile(mod_file_path, 'r') as zip_ref:
                # 查找mods.toml文件（Forge mods）
                for file_info in zip_ref.filelist:
                    if file_info.filename.endswith('mods.toml'):
                        with zip_ref.open(file_info) as f:
                            mods_toml_content = f.read().decode('utf-8')
                            mods_toml = toml.loads(mods_toml_content)
                            
                            # 解析依赖信息
                            if 'dependencies' in mods_toml:
                                for mod_id, dep_info in mods_toml['dependencies'].items():
                                    # 添加依赖的modid到列表中
                                    if isinstance(dep_info, list):
                                        for dep in dep_info:
                                            if 'modId' in dep:
                                                dep_mod_id = dep['modId']
                                                # 忽略系统级依赖
                                                if dep_mod_id not in ['minecraft', 'forge', 'neoforge']:
                                                    dependencies.append(dep_mod_id)
                                    elif isinstance(dep_info, dict) and 'modId' in dep_info:
                                        dep_mod_id = dep_info['modId']
                                        # 忽略系统级依赖
                                        if dep_mod_id not in ['minecraft', 'forge', 'neoforge']:
                                            dependencies.append(dep_mod_id)
                                        
                            # 检查是否有其他格式的依赖声明
                            if 'mods' in mods_toml:
                                for mod_entry in mods_toml['mods']:
                                    if 'dependencies' in mod_entry:
                                        deps = mod_entry['dependencies']
                                        if isinstance(deps, list):
                                            for dep in deps:
                                                if 'modId' in dep:
                                                    dep_mod_id = dep['modId']
                                                    # 忽略系统级依赖
                                                    if dep_mod_id not in ['minecraft', 'forge', 'neoforge']:
                                                        dependencies.append(dep_mod_id)
                                        elif isinstance(deps, dict) and 'modId' in deps:
                                            dep_mod_id = deps['modId']
                                            # 忽略系统级依赖
                                            if dep_mod_id not in ['minecraft', 'forge', 'neoforge']:
                                                dependencies.append(dep_mod_id)
                                            
                        break  # 找到第一个mods.toml就停止
                        
                # 查找fabric.mod.json文件（Fabric mods）
                for file_info in zip_ref.filelist:
                    if file_info.filename == 'fabric.mod.json':
                        with zip_ref.open(file_info) as f:
                            fabric_json_content = f.read().decode('utf-8')
                            fabric_json = json.loads(fabric_json_content)
                            
                            # 解析Fabric依赖信息
                            if 'depends' in fabric_json:
                                depends = fabric_json['depends']
                                if isinstance(depends, dict):
                                    for mod_id in depends:
                                        # 忽略系统级依赖
                                        if mod_id not in ['minecraft', 'fabricloader', 'java']:
                                            dependencies.append(mod_id)
                                elif isinstance(depends, list):
                                    for dep in depends:
                                        if isinstance(dep, dict) and 'id' in dep:
                                            mod_id = dep['id']
                                            if mod_id not in ['minecraft', 'fabricloader', 'java']:
                                                dependencies.append(mod_id)
                                            
                            if 'recommends' in fabric_json:
                                recommends = fabric_json['recommends']
                                # 推荐依赖暂时不处理
                                
                        break  # 找到第一个fabric.mod.json就停止
                        
        except Exception as e:
            print(f"读取 {os.path.basename(mod_file_path)} 的配置文件时出错: {str(e)}")
            
        return dependencies
        
    def get_game_version_info(self, base_path):
        """
        从游戏版本路径下的PCL目录中读取Setup.ini文件，获取MC版本、加载器类型和加载器版本
        返回: (mc_version, loader_type, loader_version) 或 (None, None, None) 如果文件不存在或读取失败
        """
        try:
            # 构建Setup.ini文件路径
            setup_ini_path = os.path.join(base_path, "PCL", "Setup.ini")
            
            # 检查文件是否存在
            if not os.path.exists(setup_ini_path):
                print(f"Setup.ini文件不存在: {setup_ini_path}")
                return None, None, None
                
            # 读取Setup.ini文件
            with open(setup_ini_path, 'r', encoding='utf-8') as f:
                lines = f.readlines()
            
            # 初始化变量
            mc_version = None
            loader_type = None
            loader_version = None
            
            # 解析文件内容
            for line in lines:
                line = line.strip()
                if line.startswith("VersionOriginal:"):
                    mc_version = line.split(":", 1)[1].strip()
                elif line.startswith("VersionForge:") and line != "VersionForge:":
                    loader_type = "Forge"
                    loader_version = line.split(":", 1)[1].strip()
                elif line.startswith("VersionFabric:") and line != "VersionFabric:":
                    loader_type = "Fabric"
                    loader_version = line.split(":", 1)[1].strip()
                elif line.startswith("VersionNeoForge:") and line != "VersionNeoForge:":
                    loader_type = "NeoForge"
                    loader_version = line.split(":", 1)[1].strip()
            
            # 如果没有找到特定的加载器版本，但找到了MC版本，设置默认加载器类型
            if mc_version and not loader_type:
                # 可以根据需要设置默认加载器类型，这里暂时留空
                pass
                
            return mc_version, loader_type, loader_version
            
        except Exception as e:
            print(f"读取Setup.ini文件时出错: {str(e)}")
            return None, None, None
            
    def download_server_core(self, server_folder_path, mc_version, loader_type, loader_version, use_mirror=True):
        """
        下载服务端核心文件
        :param server_folder_path: 服务端文件夹路径
        :param mc_version: Minecraft版本
        :param loader_type: 加载器类型 (Forge, Fabric, NeoForge)
        :param loader_version: 加载器版本
        :param use_mirror: 是否使用镜像源下载
        """
        try:
            # 根据加载器类型构建下载URL
            download_url = None
            file_name = "server.jar"
            
            if loader_type == "Forge":
                if use_mirror and self.mirror_sources:
                    # 使用镜像源下载Forge
                    download_url = f"{self.mirror_sources}/net/minecraftforge/forge/{mc_version}-{loader_version}/forge-{mc_version}-{loader_version}-installer.jar"
                else:
                    # 使用官方源下载Forge
                    download_url = f"https://maven.minecraftforge.net/net/minecraftforge/forge/{mc_version}-{loader_version}/forge-{mc_version}-{loader_version}-installer.jar"
                file_name = f"forge-{mc_version}-{loader_version}-installer.jar"
                
            elif loader_type == "NeoForge":
                if use_mirror and self.mirror_sources:
                    # 使用镜像源下载NeoForge
                    download_url = f"{self.mirror_sources}/releases/net/neoforged/neoforge/{loader_version}/neoforge-{loader_version}-installer.jar"
                else:
                    # 使用官方源下载NeoForge
                    download_url = f"https://maven.neoforged.net/releases/net/neoforged/neoforge/{loader_version}/neoforge-{loader_version}-installer.jar"
                file_name = f"neoforge-{loader_version}-installer.jar"
                
            elif loader_type == "Fabric":
                # Fabric的下载需要先获取最新的installer版本
                installer_version = self.get_latest_fabric_installer_version()
                print(f"正在获取最新的Fabric安装器版本: {installer_version}")
                if installer_version:
                    # 使用官方源下载Fabric
                    download_url = f"https://meta.fabricmc.net/v2/versions/loader/{mc_version}/{loader_version}/{installer_version}/server/jar"
                    file_name = f"fabric-server-{mc_version}-{loader_version}.jar"
            
            if download_url:
                print(f"正在下载服务端核心文件: {file_name}")
                print(f"下载地址: {download_url}")
                
                # 下载文件
                server_jar_path = os.path.join(server_folder_path, file_name)
                urllib.request.urlretrieve(download_url, server_jar_path)
                print(f"服务端核心文件下载完成: {server_jar_path}")
                return True
            else:
                print(f"暂不支持的加载器类型或无法构建下载URL: {loader_type}")
                return False
                
        except urllib.error.URLError as e:
            print(f"下载服务端核心文件失败 (网络错误): {str(e)}")
            return False
        except Exception as e:
            print(f"下载服务端核心文件失败: {str(e)}")
            return False
            
    def get_latest_fabric_installer_version(self):
        """
        获取最新的Fabric installer版本
        """
        try:
            response = requests.get("https://meta.fabricmc.net/v2/versions/installer")
            if response.status_code == 200:
                installers = response.json()
                # 返回第一个（最新的）稳定版本
                for installer in installers:
                    if installer.get("stable", False):
                        return installer.get("version")
                # 如果没有稳定版本，返回第一个版本
                if installers:
                    return installers[0].get("version")
            return None
        except Exception as e:
            print(f"获取Fabric installer版本失败: {str(e)}")
            return None
            
    def clear_server_folder(self, server_folder_path):
        """
        清空服务端文件夹
        """
        try:
            if os.path.exists(server_folder_path):
                import shutil
                # 删除文件夹中的所有内容，但保留文件夹本身
                for item in os.listdir(server_folder_path):
                    item_path = os.path.join(server_folder_path, item)
                    if os.path.isfile(item_path) or os.path.islink(item_path):
                        os.unlink(item_path)
                    elif os.path.isdir(item_path):
                        shutil.rmtree(item_path)
                print(f"已清空服务端文件夹: {server_folder_path}")
            return True
        except Exception as e:
            print(f"清空服务端文件夹失败: {str(e)}")
            return False

    def get_server_required_mods(self, mods_folder_path):
        """
        获取服务端所需的mod列表
        返回: (required_mods, optional_mods)
        """
        required_mods = []  # 必需的mods
        optional_mods = []  # 可选的mods
        required_dependencies = set()  # 必需的前置mods
        mod_file_dict = {}  # modid到文件路径的映射字典
        
        # 获取所有jar文件
        jar_files = []
        for file in os.listdir(mods_folder_path):
            if file.endswith('.jar'):
                jar_files.append(os.path.join(mods_folder_path, file))
        
        # 遍历每个mod文件
        for jar_file in jar_files:
            # 获取mod信息
            mod_info = self.classifier.processor.get_mod_info(jar_file)
            if isinstance(mod_info, tuple) and len(mod_info) == 2:
                modid, displayName = mod_info
            else:
                modid = mod_info
                displayName = modid
                
            # 记录modid到文件路径的映射
            mod_file_dict[modid] = jar_file
            
            # 使用分类器判断mod类型
            classification = self.classifier.classify_mod(jar_file)
            
            if classification == 'required':
                # 必需mod
                required_mods.append(jar_file)
                
                # 获取前置mod（忽略minecraft、forge和neoforge）
                dependencies = self.get_mod_dependencies(jar_file)
                for dep in dependencies:
                    if dep not in ['minecraft', 'forge', 'neoforge']:
                        required_dependencies.add(dep)
                        
            elif classification == 'optional':
                # 可选mod
                optional_mods.append(jar_file)
        
        # 递归查找所有必需前置的前置依赖
        all_required_dependencies = set(required_dependencies)
        dependencies_to_check = list(required_dependencies)
        
        while dependencies_to_check:
            current_dep = dependencies_to_check.pop()
            # 如果当前依赖有对应的文件，则获取其前置依赖
            if current_dep in mod_file_dict:
                dep_jar_file = mod_file_dict[current_dep]
                sub_dependencies = self.get_mod_dependencies(dep_jar_file)
                
                for sub_dep in sub_dependencies:
                    # 忽略系统级依赖
                    if sub_dep not in ['minecraft', 'forge', 'neoforge', 'fabricloader', 'java']:
                        # 如果是新发现的依赖，则添加到待检查列表中
                        if sub_dep not in all_required_dependencies:
                            all_required_dependencies.add(sub_dep)
                            dependencies_to_check.append(sub_dep)
        
        # 根据词典查找所需前置mod的文件名，并添加到必需mod列表中
        for dep_modid in all_required_dependencies:
            if dep_modid in mod_file_dict:
                dep_file_path = mod_file_dict[dep_modid]
                # 避免重复添加
                if dep_file_path not in required_mods:
                    required_mods.append(dep_file_path)
                    # 从可选列表中移除（如果存在）
                    if dep_file_path in optional_mods:
                        optional_mods.remove(dep_file_path)
        
        return required_mods, optional_mods